gh-151099: Better repr output for template strings.#151104
Conversation
loic-simon
left a comment
There was a problem hiding this comment.
We should update pprint functions output accordingly (introduced here, I can lend a hand if needed!)
|
|
||
| int res = Py_ReprEnter(self); | ||
| if (res != 0) { | ||
| return (res > 0 ? PyUnicode_FromString("Template(...)") : NULL); |
There was a problem hiding this comment.
should we use _PyType_Name(Py_TYPE(self)) instead of hardcoding Template here?
There was a problem hiding this comment.
I've updated the patch to do that.
And I also changed the call to Py_ReprEnter/Py_ReprLeave to pass op instead of self to avoid compiler warnings.
There was a problem hiding this comment.
I tried updating pprint.PrettyPrinter._pprint_template() like this
--- a/Lib/pprint.py
+++ b/Lib/pprint.py
@@ -742,13 +742,9 @@ def _pprint_template(self, object, stream, indent, allowance, context, level):
else:
indent += len(cls_name) + 1
- items = (
- ("strings", object.strings),
- ("interpolations", object.interpolations),
- )
stream.write(self._format_block_start(cls_name + "(", indent))
- self._format_namespace_items(
- items, stream, indent, allowance, context, level
+ self._format_items(
+ object, stream, indent, allowance, context, level
)but somehow this gives me an extra level of indentation
>>> import pprint
>>> print(pprint.pformat(t'Hello {'world'}', width=40, indent=4, expand=True))
Template(
'Hello ',
Interpolation(
value='world',
expression="'world'",
conversion=None,
format_spec='',
),
)
>>> print(pprint.pformat(t'Hello {'world'}', width=40, indent=4, expand=False))
Template( 'Hello ',
Interpolation( 'world',
"'world'",
None,
''))
What am I doing wrong?
There was a problem hiding this comment.
Hm, I believe that's the indented output! If you try
>>> print(pprint.pformat(['Hello', 'foo'*10], width=40, indent=4, expand=False))
[ 'Hello',
'foofoofoofoofoofoofoofoofoofoo']the extra indentation is the same, even if I would not have expected it either 😅
There was a problem hiding this comment.
The expand=False output is indeed unexpected, but the expand=True output is wrong, since the first indentation level is 8 spaces and the second level is 4.
There was a problem hiding this comment.
Okay, I think it's because we don't need the indent += self._indent_per_level with self.format_items, otherwise we ident twice:
--- a/Lib/pprint.py
+++ b/Lib/pprint.py
@@ -739,7 +739,5 @@ def _pprint_template(self, object, stream, indent, allowance, context, level):
cls_name = object.__class__.__name__
- if self._expand:
- indent += self._indent_per_level
- else:
+ if not self._expand:
indent += len(cls_name) + 1That still doesn't look super nice, but not worse than today!
There was a problem hiding this comment.
OK, with your change, this looks better:
>>> pprint.pprint(t"a{2}b", width=40)
Template('a',
Interpolation(2,
'2',
None,
''),
'b')but the first level is still indented one space too much.
For expand=True the result looks OK:
>>> pprint.pprint(t"a{2}b", width=40, expand=True, indent=4)
Template(
'a',
Interpolation(2, '2', None, ''),
'b',
)There was a problem hiding this comment.
Looks like we should remove the + 1 then😅
--- a/Lib/pprint.py
+++ b/Lib/pprint.py
@@ -739,4 +739,4 @@ def _pprint_template(self, object, stream, indent, allowance, context, level):
cls_name = object.__class__.__name__
if not self._expand:
- indent += len(cls_name) + 1
+ indent += len(cls_name)
Gives
expand=FalseTemplate('Hello ', Interpolation('world', "'world'", None, ''))
expand=False, indent=4Template( 'Hello ', Interpolation( 'world', "'world'", None, ''))
expand=TrueTemplate( 'Hello ', Interpolation( value='world', expression="'world'", conversion=None, format_spec='', ), )
expand=True, indent=4Template( 'Hello ', Interpolation( value='world', expression="'world'", conversion=None, format_spec='', ), )
It's still a bit strange for expand=False, indent=4, but that's because self._format_items is fundamentally made for collections (bracket/brace delimiter) and not classes. This issue already exists with Interpolation, so I think it's ok to stop here for this PR.
Pass the original `op` to `Py_ReprEnter`/`Py_ReprLeave` to avoid compiler warnings.
This changes the
reprouput for template strings to list the template parts in their original order (which is the same order in which those parts can be passed to theTemplateconstructor to recreate theTemplateobject).This has been discussed here: https://discuss.python.org/t/repr-output-of-t-strings/107653/8
The issue is here: #151099
reprforstring.templatelib.Template. #151099